#!/usr/bin/python2.4
#
# Copyright 2011 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


"""Base model for all layer models.

The Base model for all layer models.  All models have a url for retrieving
their layer manifest and an id for keeping layers in sorted order.  The class
also defines common functionality that can be overloaded by derived classes.

  Base: The base layer for all other layers.
"""

__author__ = 'jasonstredwick@google.com (Jason Stredwick)'


# Disable 'Import not at top of file' lint error.
# pylint: disable-msg=C6204
try:
  from google.appengine.ext import db
except ImportError:
  # For unit testing.
  from google.appengine.ext import db


class BaseId(db.Model):
  """A model class for creating unique ids for layers.

  Fields:
    counter: An integer used to create a unique id.
  """
  # TODO(jasonstredwick): Figure out a more permanent solution for ids.
  counter = db.IntegerProperty(required=False, default=0)


class Base(db.Model):
  """The base layer for all other layers.

  Fields:
    id: An integer used to maintain layer order.
    url: A string containing the name of the layer.
  """
  id = db.IntegerProperty(required=True)
  url = db.StringProperty(required=True)

  def ToDict(self):
    """Converts model into a dictionary with useful layer information.

    Returns:
      Dict containing the model data.
    """
    return {'url': self.url}


def _AllocateId():
  """Allocate a unique id for new layers.

  The function allocates a unique integer.  It is expected to be run in a
  transaction, so it can not use get_or_insert function as it also runs as
  a transaction.  A transaction can not be run if the code is already in a
  transaction.

  Returns:
    A unique integer.
  """
  base_id = BaseId.get_by_key_name('base-layer-id-generator')
  if not base_id:
    base_id = BaseId(key_name='base-layer-id-generator')

  new_id = base_id.counter
  base_id.counter += 1
  base_id.put()

  return new_id


def GetId():
  return db.run_in_transaction(_AllocateId)

